gusucode.com > VC++ 界面很酷的一款多媒体播放器 > VC++ 界面很酷的一款多媒体播放器/gusucode/xMedia代码注释中/videownd.cpp

    //Download by http://www.NewXing.com
/****************************************
*	File:			Videownd.cpp		*
*	Last modified:	2004.2.15			*
*	Author:			Yuanyi-Zhang		*
*	Version:		0.0.1.0				*
*	CopyLeft 2004   xMedia team			*
****************************************/
/****************************************************************
*																*
* This file may be distributed and/or modified under the terms	*
* of the GNU General Public License version 2 as published by	*
* the Free Software Foundation and appearing in the file		*
* LICENSE.GPL included in the packaging of this file.			*
*																*
****************************************************************/

#pragma warning(disable:4786)

#include <tchar.h>
#include <windows.h>
#include <commctrl.h>
#include <assert.h>

#include "util.h"
#include "messagedef.h"
#include "Videowindow.h"

//////////////////////////////////
VideoWnd::VideoWnd(): m_hWnd( NULL ), m_ErrorString( _T("") ), 
			m_HasCreated(false), m_ClassName( _T("VideoWnd") ),
			m_lpIL(0), m_LButtonDown(false), m_Show(false)
{
	m_hDCBack = NULL;
	m_hBmpBack = NULL;
	m_hMainBmp = NULL;
	m_hMaskBmp = NULL;
	m_hElemBmp = NULL;
	m_PlayProg = -1;
}
///////////////////////////////////
//注册窗口类
BOOL VideoWnd::RegisterClass( HINSTANCE hInstance )
{
	WNDCLASSEX	wndclass;

	ZeroMemory(&wndclass, sizeof(wndclass));

	//Window class for the main application parent window
	wndclass.cbSize			= sizeof(wndclass);
	wndclass.style			= 0;
	wndclass.lpfnWndProc	= WndProc;
	wndclass.cbClsExtra		= 0;
	wndclass.cbWndExtra		= 0;
	wndclass.hInstance		= hInstance;
	wndclass.hIcon			= 0;
	wndclass.hCursor		= LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground	= (HBRUSH)(COLOR_BTNFACE+1);
	wndclass.lpszMenuName	= 0;
	wndclass.lpszClassName	= m_ClassName.c_str();
	wndclass.hIconSm		= 0;

	return RegisterClassEx(&wndclass);
}
//////////////////////////////////
//创建视频窗口
bool VideoWnd::Create( HINSTANCE hInstance, HWND Parent)
{
	if( m_HasCreated )
	{
		m_ErrorString=_T("错误,重复创建主窗口!");
		return false;
	}

	if( !RegisterClass( hInstance ) )
	{
		m_ErrorString=_T("注册窗口类失败!");
		return false;
	}

	MDICREATESTRUCT mdic;
	memset(& mdic, 0, sizeof(mdic));
	mdic.lParam = (LPARAM) this;

	HWND hWnd=CreateWindowEx( WS_EX_TOOLWINDOW,
		m_ClassName.c_str(), NULL,
		WS_POPUP, 
		0, 0, 100, 100,
		Parent, 0,
		hInstance, &mdic );

	if(hWnd==NULL)
	{
		m_ErrorString = _T( "创建视频窗口失败,不明错误!" );
		return false;
	}

	if( !InitTooltips( hWnd, hInstance ) )
	{
		return false;
	}

	m_ErrorString = _T( "" );
	return true;
}
/////////////////////////////////////
//读取皮肤配置
bool VideoWnd::LoadSkinConfig()
{
	if( m_lpIL == NULL )
	{
		m_ErrorString = _T("未设置配置文件");
		return false;
	}

	string	strWndRect;

	strWndRect = m_lpIL->Get( _T( "vwwindowrect" ) );

	if( strWndRect.compare( _T( "" ) ) == 0 )
	{
		m_ErrorString = _T("配置文件不完整,无法读取所需信息!");
		return false;
	}

	m_WndRect = StringToRect( strWndRect );

	strWndRect = m_lpIL->Get( _T( "vwvideowndrect" ) );

	if( strWndRect.compare( _T( "" ) ) == 0 )
	{
		m_ErrorString = _T("配置文件不完整,无法读取所需信息!");
		return false;
	}

	m_VideoRect = StringToRect( strWndRect );

	m_SkinName = m_lpIL->Get( _T( "skinname" ) );

	m_vecElement.push_back( Element( _T("vwfbbutton"), m_lpIL, XM_VWFBBUTTON, true ) );
	m_vecElement.push_back( Element( _T("vwffbutton"), m_lpIL, XM_VWFFBUTTON, true ) );
	m_vecElement.push_back( Element( _T("vwstopbutton"), m_lpIL, XM_VWSTOPBUTTON, true ) );
	m_vecElement.push_back( Element( _T("vwplaybutton"), m_lpIL, XM_VWPLAYBUTTON, true ) );
	m_vecElement.push_back( Element( _T("vwpausebutton"), m_lpIL, XM_VWPAUSEBUTTON, true ) );
	m_vecElement.push_back( Element( _T("vwprogslider"), m_lpIL, XM_VWPROGSLIDER, true ) );
	m_vecElement.push_back( Element( _T("vwprogbar"), m_lpIL, XM_VWPROGBAR, true ) );

	return true;
}
//////////////////////////////////////
//将窗口消息发送到视频窗口俄消息处理函数
LRESULT CALLBACK VideoWnd::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam,
							 LPARAM lParam )
{
	VideoWnd *pMainWnd;
	if ( uMsg==WM_NCCREATE )
	{   
		assert( ! IsBadReadPtr((void *) lParam, sizeof(CREATESTRUCT)) );
		MDICREATESTRUCT * pMDIC = (MDICREATESTRUCT *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
		
		if( pMDIC )
			pMainWnd = ( VideoWnd *) (pMDIC->lParam);
		else
			return 0;

		assert( ! IsBadReadPtr(pMainWnd, sizeof( VideoWnd ) ) );
		SetWindowLong(hWnd, GWL_USERDATA, (LONG) pMainWnd);
	}
	else
		pMainWnd=( VideoWnd *)GetWindowLong(hWnd, GWL_USERDATA);
	
	return pMainWnd->MsgProc( hWnd, uMsg, wParam, lParam );
}
//////////////////////////////////////////
//消息处理函数
long VideoWnd::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
	POINT p;
	switch( uMsg )
	{
	case WM_CREATE:
		m_hWnd = hWnd;
		if( !initials( hWnd ) )
		{
			MessageBox( hWnd, GetErrorString().c_str(), "错误", MB_OK|MB_ICONWARNING );
		}
		break;
	case WM_PAINT:
		onDraw();
		break;
	case WM_LBUTTONDOWN:
		SetCapture( hWnd );
		p.x = LOWORD(lParam);
		p.y = HIWORD(lParam);
		ClientToScreen( hWnd, &p );
		onLButtonDown( p );
		break;
	case WM_MOUSEMOVE:
		GetCursorPos( &p );
		onMouseMove( p );
		break;
	case WM_LBUTTONUP:
		ReleaseCapture();
		p.x = LOWORD(lParam);
		p.y = HIWORD(lParam);
		ClientToScreen( hWnd, &p );
		onLButtonUp( p );
		break;
	case XM_VWPROGBAR:
		switch( wParam )
		{
		case ELEM_MOUSEMOVE:
			adjustProg();
			break;
		case ELEM_LBUTTONUP:
			PostThreadMessage( GetCurrentThreadId(), MC_SEEKING, 0l, 0l );
			break;
		}
        break;
	}
	return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
		
//////////////////////////////////////
//初始化视频窗口
bool VideoWnd::initials( HWND hwnd )
{
	if( !InitDC() )
	{
		m_ErrorString = _T("初始化DC失败!");
		return false;
	}
	SetWindowSize();

	if( !LoadResource() )
	{
		return false;
	}

//	SetWindowRegion();
	
	m_HasCreated = true;
	return true;
}

//////////////////////////
//初始化DC
bool VideoWnd::InitDC()
{
	if( m_hDCBack )
	{
		DeleteObject( m_hDCBack );
	}
	if( m_hBmpBack )
	{
		DeleteObject( m_hBmpBack );
	}

	HDC hdc;
	hdc = GetDC( m_hWnd );
	
	m_hDCBack = CreateCompatibleDC( hdc );
	m_hBmpBack = CreateCompatibleBitmap( hdc, 
		m_WndRect.right - m_WndRect.left,
		m_WndRect.bottom - m_WndRect.top);

	if( !m_hDCBack || !m_hBmpBack )
	{
		return false;
	}

	SelectObject( m_hDCBack, m_hBmpBack );
	return true;
}
///////////////////////	
//释放资源
void VideoWnd::ReleaseResource()
{
	if( m_hDCBack )
	{
		DeleteObject( m_hDCBack );
	}
	if( m_hBmpBack )
	{
		DeleteObject( m_hBmpBack );
	}
	if( m_hMaskBmp )
	{
		DeleteObject( m_hMaskBmp );
	}
	if( m_hMainBmp )
	{
		DeleteObject( m_hMainBmp );
	}
	if( m_hElemBmp )
	{
		DeleteObject( m_hElemBmp );
	}
}
////////////////////
//处理OnDraw消息
bool VideoWnd::onDraw( )
{
	HDC hdc,hdcImg;
	PAINTSTRUCT ps;
	hdc = BeginPaint( m_hWnd, &ps );

	hdcImg = CreateCompatibleDC( hdc );
	SelectObject( hdcImg, m_hMainBmp );
	BitBlt( m_hDCBack, 0, 0,
		m_WndRect.right - m_WndRect.left,
		m_WndRect.bottom - m_WndRect.top,
		hdcImg, 0, 0, SRCCOPY );

	vector<Element>::iterator ite;

	for( ite = m_vecElement.begin(); ite != m_vecElement.end(); ite++ )
	{
		if( !ite->onDraw( m_hDCBack, m_hElemBmp ) )
		{
			return false;
		}
	}

	BitBlt( hdc, 0, 0, m_WndRect.right - m_WndRect.left,
			m_WndRect.bottom - m_WndRect.top, m_hDCBack, 
			0, 0, SRCCOPY );
	
	EndPaint( m_hWnd, &ps );

	DeleteObject( hdcImg );
	DeleteObject( hdc );

	return true;
}
////////////////////
//读取资源
bool VideoWnd::LoadResource()
{
	if( m_hMaskBmp )
	{
		DeleteObject( m_hMaskBmp );
	}
	if( m_hMainBmp )
	{
		DeleteObject( m_hMainBmp );
	}
	if( m_hElemBmp )
	{
		DeleteObject( m_hElemBmp );
	}

	string maskBmp,mainBmp,elemBmp;

	maskBmp = _T( "skin\\" ) + m_SkinName + _T( "\\vwmask.bmp" );
	mainBmp = _T( "skin\\" ) + m_SkinName + _T( "\\vwmain.bmp" );
	elemBmp = _T( "skin\\" ) + m_SkinName + _T( "\\vwelement.bmp" );

	m_hMaskBmp = (HBITMAP)LoadImage( NULL, maskBmp.c_str(),
		IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION );

	if( !m_hMaskBmp )
	{
		m_ErrorString = _T("无法读取文件:") + maskBmp;
		return false;
	}
	
	m_hMainBmp = (HBITMAP)LoadImage( NULL, mainBmp.c_str(),
		IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION );

	if( !m_hMainBmp )
	{
		m_ErrorString = _T("无法读取文件:") + mainBmp;
		return false;
	}

	m_hElemBmp = (HBITMAP)LoadImage( NULL, elemBmp.c_str(),
		IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION );

	if( !m_hElemBmp )
	{
		m_ErrorString = _T("无法读取文件:") + elemBmp;
		return false;
	}

	return true;
}
////////////////////////////
//初始化工具提示
bool VideoWnd::InitTooltips( HWND hwnd, HINSTANCE hInst )
{
    HWND hwndTT;                 //Tooltip控件句柄

    //创建Tooltip控件
    hwndTT = CreateWindowEx(WS_EX_TOPMOST,
        TOOLTIPS_CLASS,
        NULL,
        WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,		
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        hwnd,
        NULL,
        hInst,
        NULL );
	
	if( hwndTT == NULL )
	{
		m_ErrorString = _T("创建工具提示窗口失败!");
		return false;
	}

    SetWindowPos(hwndTT,
        HWND_TOPMOST,
        0, 0, 0, 0,
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

	//这个结构体存储Tooltip控件的相关信息
    TOOLINFO ti;
	unsigned int uid = 0;   

	//初始化ti结构体成员
    ti.cbSize = sizeof(TOOLINFO);
    ti.uFlags = TTF_SUBCLASS;
    ti.hwnd = hwnd;
    ti.hinst = hInst;
    ti.uId = uid;

	TCHAR tcsTooltip[256];

	vector<Element>::iterator ite;
	RECT rect;
	string str;
    for( ite = m_vecElement.begin(); ite != m_vecElement.end(); ite++ )
	{
		rect = ite->getRectPos();
		str = ite->getTooltip();
		if( (rect.left == rect.right && rect.top == rect.bottom) ||
			str.compare( _T("") ) == 0 )
		{
			continue;
		}
		strcpy( tcsTooltip, str.c_str() );
		ti.lpszText = tcsTooltip;
	    ti.rect = rect;
		//添加工具提示
		SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);	
	}
	return true;
}
////////////////////////////
//设置窗口可见区域
void VideoWnd::SetWindowRegion()
{
	HRGN hWndRgn;
	RECT clientRect,wndRect;
	
	GetClientRect( m_hWnd, &clientRect );
	GetWindowRect( m_hWnd, &wndRect );

	POINT start = { 0, 0 };
	ClientToScreen( m_hWnd, &start );

	hWndRgn = CreateRectRgn( start.x - wndRect.left, 
		start.y - wndRect.top, 
		clientRect.right - clientRect.left + start.x - wndRect.left,
		clientRect.bottom - clientRect.top + start.y - wndRect.top );

	BITMAP bmp;
	GetObject(m_hMaskBmp, sizeof(bmp), &bmp);
	
	HRGN temp;

	HDC hdc = GetDC( m_hWnd );
	HDC hdcImg = CreateCompatibleDC( hdc );
	ReleaseDC( m_hWnd, hdc );

	SelectObject( m_hDCBack, m_hBmpBack );
	SelectObject( hdcImg, m_hMaskBmp );
	BitBlt( m_hDCBack, 0, 0,
		m_WndRect.right - m_WndRect.left,
		m_WndRect.bottom - m_WndRect.top,
		hdcImg, 0, 0, SRCCOPY );

	DeleteObject( hdcImg );

	for( int i = 0; i < bmp.bmWidth; i++ )
	{
		for( int j = 0; j < bmp.bmHeight; j++ )
		{
			if( GetPixel( m_hDCBack, i, j ) == RGB( 255, 255, 255 ) )
			{
				temp = CreateRectRgn( start.x - wndRect.left + i, 
					start.y - wndRect.top + j,
					start.x - wndRect.left + i + 1, 
					start.y - wndRect.top + j + 1 );
				CombineRgn( hWndRgn, hWndRgn, temp, RGN_XOR );
				DeleteObject( temp );
			}
		}
	}
	SetWindowRgn( m_hWnd, hWndRgn, false );
}
////////////////////////////
//处理鼠标左键按下消息
void VideoWnd::onLButtonDown( POINT p )
{
	m_LButtonDown = true;
	m_clickPos = p;
	bool isElemClicked = false;

	ScreenToClient( m_hWnd, &p );

	vector<Element>::iterator ite;
	RECT  validRect;
	for( ite = m_vecElement.begin(); ite != m_vecElement.end(); ite++ )
	{
		if( ite->onLButtonDown( p ) )
		{
			isElemClicked = true;
			validRect = ite->getRectPos();
			InvalidateRect( m_hWnd, &validRect, false );
		}
	}

	if( isElemClicked )
	{
		m_LButtonDown = false;
	}
}
//////////////////////////
//处理鼠标移动消息
void VideoWnd::onMouseMove( POINT p )
{
	RECT wndRect;
	GetWindowRect( m_hWnd, &wndRect );
	if( m_LButtonDown )
	{
		wndRect.left += p.x - m_clickPos.x;
		wndRect.right += p.x - m_clickPos.x;
		wndRect.bottom += p.y - m_clickPos.y;
		wndRect.top += p.y - m_clickPos.y;

		m_clickPos = p;

		MoveWindow(m_hWnd, wndRect.left, wndRect.top,
			wndRect.right - wndRect.left,
			wndRect.bottom - wndRect.top,
			true );
	}
	else
	{
		ScreenToClient( m_hWnd, &p );

		vector<Element>::iterator ite;
		RECT  validRect;
		for( ite = m_vecElement.begin(); ite != m_vecElement.end(); ite++ )
		{
			if( ite->onMouseMove( p ) )
			{
				validRect = ite->getRectPos();
				InvalidateRect( m_hWnd, &validRect, false );
			}
		}
	}
}
/////////////////////////
//处理鼠标左键松开消息
void VideoWnd::onLButtonUp( POINT p )
{
	if( m_LButtonDown )
	{
		m_LButtonDown = false;
	}
	else
	{
		ScreenToClient( m_hWnd, &p );
		vector<Element>::iterator ite;
		RECT  validRect;
		for( ite = m_vecElement.begin(); ite != m_vecElement.end(); ite++ )
		{
			if( ite->onLButtonUp( p ) )
			{
				validRect = ite->getRectPos();
				InvalidateRect( m_hWnd, &validRect, false );
			}
		}
	}
}
//////////////////////////////////
//通过按钮名称获取按钮
Element* VideoWnd::getElementByName( string str )
{
	vector<Element>::iterator ite;
	
	for( ite = m_vecElement.begin(); ite != m_vecElement.end(); ite++ )
	{
		if( str.compare( ite->getName() ) == 0 )
			break;
	}

	if( ite == m_vecElement.end() )
	{
		return NULL;
	}
	
	return ite;
}
////////////////////////////////////
//调整播放进度
void VideoWnd::adjustProg()
{
	Element* progressBar = getElementByName( _T("vwprogbar") );
	Element* progressSlider = getElementByName( _T("vwprogslider") );
	
	RECT validRect = progressSlider->getRectPos();
	  
	m_PlayProg = adjustSlider( progressSlider, progressBar );

	InvalidateRect( m_hWnd, &validRect, false );
}
////////////////////////////////////
//设置播放进度
void VideoWnd::setPlayProg( int prog )
{
	Element* progressBar = getElementByName( _T("vwprogbar") );
	Element* progressSlider = getElementByName( _T("vwprogslider") );
	
	RECT validRect = progressSlider->getRectPos();
	  
	adjustSlider( progressSlider, progressBar, prog );

	InvalidateRect( m_hWnd, &validRect, false );
}